{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#  XML 解析"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "'''\n",
    "\n",
    "\n",
    "Python 对 XML 的解析\n",
    "常见的 XML 编程接口有 DOM 和 SAX，这两种接口处理 XML 文件的方式不同，当然使用场合也不同。\n",
    "\n",
    "Python 有三种方法解析 XML，SAX，DOM，以及 ElementTree:\n",
    "\n",
    "1.SAX (simple API for XML )\n",
    "Python 标准库包含 SAX 解析器，SAX 用事件驱动模型，通过在解析XML的过程中触发一个个的事件并调用用户定义的回调函数来处理XML文件。\n",
    "\n",
    "2.DOM(Document Object Model)\n",
    "将 XML 数据在内存中解析成一个树，通过对树的操作来操作XML。\n",
    "\n",
    "3.ElementTree(元素树)\n",
    "ElementTree就像一个轻量级的DOM，具有方便友好的API。代码可用性好，速度快，消耗内存少。\n",
    "\n",
    "注：因DOM需要将XML数据映射到内存中的树，一是比较慢，二是比较耗内存，而SAX流式读取XML文件，比较快，占用内存少，但需要用户实现回调函数（handler）。\n",
    "\n",
    "\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "'''\n",
    "\n",
    "python使用SAX解析xml\n",
    "SAX是一种基于事件驱动的 API。\n",
    "\n",
    "利用SAX解析XML文档牵涉到两个部分: 解析器和事件处理器。\n",
    "\n",
    "解析器负责读取XML文档，并向事件处理器发送事件，如元素开始跟元素结束事件。\n",
    "\n",
    "而事件处理器则负责对事件作出响应，对传递的XML数据进行处理。\n",
    "\n",
    "1、对大型文件进行处理；\n",
    "2、只需要文件的部分内容，或者只需从文件中得到特定信息。\n",
    "3、想建立自己的对象模型的时候。\n",
    "在python中使用sax方式处理xml要先引入xml.sax中的parse函数，还有xml.sax.handler中的ContentHandler。\n",
    "\n",
    "ContentHandler类方法介绍\n",
    "characters(content)方法\n",
    "\n",
    "调用时机：\n",
    "\n",
    "从行开始，遇到标签之前，存在字符，content 的值为这些字符串。\n",
    "\n",
    "从一个标签，遇到下一个标签之前， 存在字符，content 的值为这些字符串。\n",
    "\n",
    "从一个标签，遇到行结束符之前，存在字符，content 的值为这些字符串。\n",
    "\n",
    "标签可以是开始标签，也可以是结束标签。\n",
    "\n",
    "startDocument() 方法\n",
    "\n",
    "文档启动的时候调用。\n",
    "\n",
    "endDocument() 方法\n",
    "\n",
    "解析器到达文档结尾时调用。\n",
    "\n",
    "startElement(name, attrs)方法\n",
    "\n",
    "遇到XML开始标签时调用，name是标签的名字，attrs是标签的属性值字典。\n",
    "\n",
    "endElement(name) 方法\n",
    "\n",
    "遇到XML结束标签时调用。\n",
    "\n",
    "\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "'''\n",
    "\n",
    "\n",
    "make_parser方法\n",
    "以下方法创建一个新的解析器对象并返回。\n",
    "\n",
    "xml.sax.make_parser( [parser_list] )\n",
    "参数说明:\n",
    "\n",
    "parser_list - 可选参数，解析器列表\n",
    "parser方法\n",
    "以下方法创建一个 SAX 解析器并解析xml文档：\n",
    "\n",
    "xml.sax.parse( xmlfile, contenthandler[, errorhandler])\n",
    "参数说明:\n",
    "\n",
    "xmlfile - xml文件名\n",
    "contenthandler - 必须是一个ContentHandler的对象\n",
    "errorhandler - 如果指定该参数，errorhandler必须是一个SAX ErrorHandler对象\n",
    "parseString方法\n",
    "parseString方法创建一个XML解析器并解析xml字符串：\n",
    "\n",
    "xml.sax.parseString(xmlstring, contenthandler[, errorhandler])\n",
    "参数说明:\n",
    "\n",
    "xmlstring - xml字符串\n",
    "contenthandler - 必须是一个ContentHandler的对象\n",
    "errorhandler - 如果指定该参数，errorhandler必须是一个SAX ErrorHandler对象\n",
    "\n",
    "\n",
    "\n",
    "'''"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "*****Movie*****\n",
      "Title: Enemy Behind\n",
      "Type: War, Thriller\n",
      "Format: DVD\n",
      "Year: 2003\n",
      "Rating: PG\n",
      "Stars: 10\n",
      "Description: Talk about a US-Japan war\n",
      "*****Movie*****\n",
      "Title: Transformers\n",
      "Type: Anime, Science Fiction\n",
      "Format: DVD\n",
      "Year: 1989\n",
      "Rating: R\n",
      "Stars: 8\n",
      "Description: A schientific fiction\n",
      "*****Movie*****\n",
      "Title: Trigun\n",
      "Type: Anime, Action\n",
      "Format: DVD\n",
      "Rating: PG\n",
      "Stars: 10\n",
      "Description: Vash the Stampede!\n",
      "*****Movie*****\n",
      "Title: Ishtar\n",
      "Type: Comedy\n",
      "Format: VHS\n",
      "Rating: PG\n",
      "Stars: 2\n",
      "Description: Viewable boredom\n"
     ]
    }
   ],
   "source": [
    "import xml.sax\n",
    " \n",
    "class MovieHandler( xml.sax.ContentHandler ):\n",
    "    \n",
    "    def __init__(self):\n",
    "        self.CurrentData = \"\"\n",
    "        self.type = \"\"\n",
    "        self.format = \"\"\n",
    "        self.year = \"\"\n",
    "        self.rating = \"\"\n",
    "        self.stars = \"\"\n",
    "        self.description = \"\"\n",
    "\n",
    "    # 元素开始事件处理\n",
    "    def startElement(self, tag, attributes):\n",
    "        self.CurrentData = tag\n",
    "        if tag == \"movie\":\n",
    "            print(\"*****Movie*****\")\n",
    "            title = attributes[\"title\"]\n",
    "            print(\"Title:\", title)\n",
    "\n",
    "    # 元素结束事件处理\n",
    "    def endElement(self, tag):\n",
    "        if self.CurrentData == \"type\":\n",
    "             print(\"Type:\", self.type)\n",
    "        elif self.CurrentData == \"format\":\n",
    "             print(\"Format:\", self.format)\n",
    "        elif self.CurrentData == \"year\":\n",
    "             print(\"Year:\", self.year)\n",
    "        elif self.CurrentData == \"rating\":\n",
    "             print(\"Rating:\", self.rating)\n",
    "        elif self.CurrentData == \"stars\":\n",
    "             print(\"Stars:\", self.stars)\n",
    "        elif self.CurrentData == \"description\":\n",
    "             print(\"Description:\", self.description)\n",
    "        self.CurrentData = \"\"\n",
    "\n",
    "    # 内容事件处理\n",
    "    def characters(self, content):\n",
    "        if self.CurrentData == \"type\":\n",
    "             self.type = content\n",
    "        elif self.CurrentData == \"format\":\n",
    "             self.format = content\n",
    "        elif self.CurrentData == \"year\":\n",
    "             self.year = content\n",
    "        elif self.CurrentData == \"rating\":\n",
    "             self.rating = content\n",
    "        elif self.CurrentData == \"stars\":\n",
    "             self.stars = content\n",
    "        elif self.CurrentData == \"description\":\n",
    "             self.description = content\n",
    "                \n",
    "if ( __name__ == \"__main__\"):\n",
    "\n",
    "    # 创建一个 XMLReader\n",
    "    parser = xml.sax.make_parser()\n",
    "    # turn off namepsaces\n",
    "    parser.setFeature(xml.sax.handler.feature_namespaces, 0)\n",
    "\n",
    "    # 重写 ContextHandler\n",
    "    Handler = MovieHandler()\n",
    "    parser.setContentHandler( Handler )\n",
    "\n",
    "    parser.parse(\"movies.xml\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "  "
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.1"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
